﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebShopAPI.Models;
using DAL;
using Models;
namespace WebShopAPI.Controllers
{
    /// <summary>
    /// 角色管理模块 相关功能 七个方法
    /// </summary>
    public class rolesController : ApiController
    {
        sp_roleService sp_roleService = new sp_roleService(); //角色数据服务
        sp_permissionDAL sp_perService = new sp_permissionDAL();//权限数据服务

        #region 1 角色列表
        public ResponData Get()
        {
            //查询所有角色
            List<sp_role> rolelist = sp_roleService.GetAll();
            //所有权限
            List<sp_permission> rermission = sp_perService.GetAll();
            //处理数据部分
            //1. 定义所有角色需要返回的数据格式集合
            List<OneRoleAndPermission> r_roleList = new List<OneRoleAndPermission>();
            //2.循环所有的角色对象,并转换成需要返回数据，
            foreach (var robj in rolelist)
            {
                //a 把读取出来的对象进行转换
                OneRoleAndPermission roleobj = new OneRoleAndPermission();
                roleobj.id = robj.role_id;
                roleobj.roleName=robj.role_name;
                roleobj.roleDesc = robj.role_desc;
                string strPro = ","+robj.ps_ids+",";//权限字符串
                //b 找一级角色下的一级权限
                List<sp_permission> allPer = rermission.
                    Where(
                    p => p.ps_pid==0 
                    &&
                    strPro.Contains(","+p.ps_id+",")  ).ToList();
                //c 一级角色转成需要格式
                List<MyMenuItem> myFristItem = new List<MyMenuItem>();
                foreach (sp_permission obj in allPer)
                {
                    MyMenuItem menu = new MyMenuItem()
                    {
                        id = obj.ps_id,
                        authName = obj.ps_name,
                        path = null,
                        pid = "0"
                        // path = "/" + obj.ps_c + "/" + obj.ps_a //二级才有
                    };
                    //读取该一级数据的二级
                    var secondePer = rermission.Where( p => p.ps_pid == obj.ps_id  
                    &&
                      strPro.Contains("," + p.ps_id + ",")

                    ).Select(
                        p => new MyMenuItem
                        {
                            id = p.ps_id,
                            authName = p.ps_name,
                            path = null, //
                            pid = obj.ps_id + "",
                            children = rermission.Where(

                                p3 => p3.ps_pid == p.ps_id
                                &&
                                strPro.Contains("," + p3.ps_id + ",")

                            ).Select(p4 => new MyMenuItem
                            {
                                id = p4.ps_id,
                                authName = p4.ps_name,
                                path = null, //二级才有
                                pid = obj.ps_id + "," + p.ps_id,

                            }).ToList()
                        }
                        );
                    //修改一级的二级菜单集合
                    menu.children = secondePer.ToList();
                    ///////////////////////////////////////
                    myFristItem.Add(menu);//加入到所有菜单集合中  

                }
                //加入到一级
                roleobj.children = myFristItem;
                //3 处理好每一个角色的数据后加入到集合中======//
                r_roleList.Add(roleobj);
            }
            /////////响应数据部分//////////////////////////
            ResponData responData = new ResponData();
            responData.data = r_roleList;//设置数据
            responData.meta.msg = "获取成功";
            responData.meta.status = 200;//
            return responData;
        }
        #endregion

        #region 2 添加角色
        public ResponData Post(AddRole roleobj)
        {
            //传过来的对象,结构与数据库后台对象不一样,在这可转换,也可以在数据服务层转换  
            sp_role role = new sp_role();
            role.role_name = roleobj.roleName;
            role.role_desc = roleobj.roleDesc;
            role.ps_ids = "";//界面没有传过来,但是数据库非空的

            sp_roleService.Add(role); //对象的id会变化了
            //改造一下增加方法,直接返回一个对象
            /////////////////////
            ResponData rd = new ResponData();
            rd.data = new
            {
                roleId = role.role_id,
                roleName = role.role_name,
                roleDesc = role.role_desc
            };
            rd.meta.msg = "创建成功";
            rd.meta.status = 201;
            return rd;
        }
        #endregion                              

        #region 3 根据ID查询角色 
        /// <summary>
        /// 查询角色
        /// </summary>
        /// <param name="id">id可以由路由参数</param>
        /// <returns></returns>
        public ResponData Get(int id)
        { 
            sp_role roleobj= sp_roleService.GetOne(id);

            //处理成前端要求
            ResponData rd = new ResponData();
            rd.data = new 
            { 
                roleId= roleobj.role_id,
                roleName=roleobj.role_name,
                roleDesc=roleobj.role_desc
            };//格式与获取的对象结构不一样，需要处理成功要的样式
            rd.meta.msg = "获取成功";
            rd.meta.status = 200;

            return rd;
        }
        #endregion

        #region 4 编辑提交角色
        public ResponData Put(int id, AddRole roleobj)
        {
            //转换
            sp_role role = sp_roleService.GetOne(id);//先查一个对象
            role.role_name = roleobj.roleName; //修改值
            role.role_desc = roleobj.roleDesc;
            //调用数据服务
            sp_roleService.Modify(role);
            ///////////////////
            ResponData rd = new ResponData();
            rd.data = new
            {
                roleId = role.role_id,
                roleName = role.role_name,
                roleDesc = role.role_desc
            };
            rd.meta.msg = "创建成功";
            rd.meta.status = 201;
            return rd;
        }
        #endregion

        #region 5 删除角色
        public ResponData Delete(int id)
        {
            //调用删除，如果成功，删除前也可以进行一些判断检查是否有外键引用,可以使用逻辑删除，改变状态
            sp_roleService.DeleteOne(id);
            //

            ResponData rd = new ResponData();
            rd.data = null;
            rd.meta.msg = "删除成功";
            rd.meta.status = 200;
            return rd;
        }
        #endregion

        #region 6 角色授权 自定义路由 api与其他的路径前缀一样 post只传一个数据时，要加上FromBody]才有效
        [Route("api/roles/{roleid}/rights")]
        public ResponData Post(int roleid, Rights obj)
        {
            //
            sp_role role = sp_roleService.GetOne(roleid);//先查一个对象
            role.ps_ids= obj.rids;//设置权限字符串
            sp_roleService.Modify(role);
            //
            ResponData rd = new ResponData();
            rd.data = null;
            rd.meta.msg = "更新成功";
            rd.meta.status = 200;
            return rd;
        }
        #endregion

        #region 7 删除角色的指定权限
        /// <summary>
        /// 
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="rightId"></param>
        /// <returns></returns>
        [Route("api/roles/{roleId}/rights/{rightId}")]
        public ResponData Delete(int roleId,int rightId)
        {
            ////////查询出角色有的权限，由于是字符串格式，称换成字符串数组，再组装，删除后，再写回数据库////////
            sp_role spcha = sp_roleService.GetOne(roleId);
            //找出权限字符串
            string existsRights = spcha.ps_ids;
            string[] exsplitRigths = existsRights.Split(',');
            //除删除后的权限
            List<string> strRights = new List<string>();
            foreach (var s in exsplitRigths)
            {
                if ( int.Parse(s) != rightId) 
                {
                    strRights.Add(s);
                }
            }
            //把排除删删除后的权限节点构建成,1,2,3...这种形式
            string strPro = "";
            for (int i = 0; i < strRights.Count; i++)
            {
                strPro = strPro + strRights[i] +",";
            }
            if (strPro.Length > 0) //去掉最后一个,号
            {
                strPro = strPro.Substring(0, strPro.Length - 1);
            }
            //调用修改
            spcha.ps_ids = strPro;//改后的字符串
            sp_roleService.Modify(spcha);//调用修改语句
            strPro = "," + strPro + ",";
            //////////////查询该角色有的权限一级二级等结构数据/////////////////////////////////////
            List<sp_permission> rermission = sp_perService.GetAll();
            //b 找一级角色下的一级权限
            List<sp_permission> allPer = rermission.
                Where(
                p => p.ps_pid == 0
                &&
                strPro.Contains("," + p.ps_id + ",")).ToList();
            //c 一级角色转成需要格式
            List<MyMenuItem> myFristItem = new List<MyMenuItem>();
            foreach (sp_permission obj in allPer)
            {
                MyMenuItem menu = new MyMenuItem()
                {
                    id = obj.ps_id,
                    authName = obj.ps_name,
                    path = null,
                    pid = "0"
                    // path = "/" + obj.ps_c + "/" + obj.ps_a //二级才有
                };
                //读取该一级数据的二级
                var secondePer = rermission.Where(p => p.ps_pid == obj.ps_id
                &&
                  strPro.Contains("," + p.ps_id + ",")

                ).Select(
                    p => new MyMenuItem
                    {
                        id = p.ps_id,
                        authName = p.ps_name,
                        path = null, //
                        pid = obj.ps_id + "",
                        children = rermission.Where(

                            p3 => p3.ps_pid == p.ps_id
                            &&
                            strPro.Contains("," + p3.ps_id + ",")

                        ).Select(p4 => new MyMenuItem
                        {
                            id = p4.ps_id,
                            authName = p4.ps_name,
                            path = null, //二级才有
                            pid = obj.ps_id + "," + p.ps_id,

                        }).ToList()
                    }
                    );
                //修改一级的二级菜单集合
                menu.children = secondePer.ToList();
                ///////////////////////////////////////
                myFristItem.Add(menu);//加入到所有菜单集合中  

            }
            //////////////////////////////////////////////////////////////////////////////////////
            ResponData rd = new ResponData();
            rd.data = myFristItem;//所有一级集合，二级三级后续读出
            rd.meta.msg = "取消权限成功";
            rd.meta.status = 200;
            return rd;
        }
        #endregion
                                                                                                          
    }

    /// <summary>
    /// 角色及其+权限数据一起返回，定义一个类
    /// </summary>
    public class OneRoleAndPermission
    { 
        public int id { get; set; } //角色编号id
        public string roleName { get; set; } //角色名

        public string roleDesc { get; set; } //角色描述

        //权限列表，级联数据保存
        public List<MyMenuItem> children { get; set; }

    }

    //添加角色post 两个参数,也需要创建类
    public class AddRole
    { 
        public string roleName { get; set; }
        public string roleDesc { get; set; }
    }

    public class Rights
    {
        public string rids { get; set; }
    }

}
